#include "defines.h"
#include "lib.h"
#include "kozos.h"
#include "intr.h"

#define MARA    ((volatile uint32 *) 0xffff20)
#define MARB    ((volatile uint32 *) 0xffff28)
#define ETCRA   ((volatile uint16 *) 0xffff24)
#define DTCRA   ((volatile uint8 *) 0xffff27)
#define DTCRB   ((volatile uint8 *) 0xffff2f)

static kz_thread_id_t id;
static kz_msgbox_id_t mb;

static void intr()
{
    puts("INTR\n");
    *DTCRB = 0;
    *DTCRA = 0;
    // kz_wakeup(id);
    kz_send(mb, 0, NULL, 0);
}

int testdma(int argc, char *argv[])
{
    id = kz_getid();
    mb = kz_getmsgbox();
    kz_setintr(SOFTVEC_TYPE_DMAC0, intr);

    memset((void *)0x480000, 10, 0x10000);
    memset((void *)0x500000, 100, 0x10000);

    // memcpy((void *)0x500000, (void *)0x480000, 0x10000) と同等
    *MARA = 0x480000;
    *MARB = 0x500000;
    *ETCRA = 0;         // 0は0x10000を意味する
    *DTCRB = 0x12;      // サイクルスチールモード
    INTR_DISABLE;
    *DTCRA = 0x1e;
    *DTCRB |= 0x80;
    *DTCRA |= 0x80;
    INTR_ENABLE;

    // kz_sleep(); // sleep-wakeupだとsleep完了前に転送完了した場合×
    kz_recv(mb, NULL, NULL);

    memset((void *)0x580000, 10, 0x10000);

    if (!memcmp((void *)0x580000, (void *)0x480000, 0x10000)
        && !memcmp((void *)0x580000, (void *)0x500000, 0x10000))
        puts("DMA succeeded.\n");
    else
        puts("DMA failed.\n");

    kz_setintr(SOFTVEC_TYPE_DMAC0, NULL);
    kz_freemsgbox(mb);
    return 0;
}
